#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define CHECK(tree) if( tree_cycle_ok(tree) == CYCLE_IN_TREE ) { Print_tree(tree); printf("\n line :%d time : %s " , __LINE__ , __TIME__); }

const int MAX_DATA_SIZE = 20;
const int MAX_TREE_SIZE = 100;

const int CYCLE_IN_TREE = -1;
const int POISON = 666;

const int CHISLO_TYPE    = 130;

const int VAR_TYPE       = 120;
const int FUNCTION_TYPE  = 110;

const int CONNECTION_TYPE = 111;

struct info_tree
{

    char symbol;

    int  value;

    char var[MAX_DATA_SIZE];

    char func[MAX_DATA_SIZE];

    int flag;

};

struct tree_t
{

	info_tree data;

	tree_t* right;
	tree_t* left;

};


//================================================================================================================================================================================

// functions

tree_t* New_tree_branch(info_tree* get_inform , tree_t* right , tree_t* left  );

void  tree_destruct(tree_t* tree);

void Print_tree(tree_t* tree);
void Print_tree_postfiks(tree_t* tree);

int tree_cycle_ok(tree_t* tree);
void tree_dump(tree_t* tree);

tree_t* copy_tree(tree_t* tree);

int importance(tree_t* tree);

//================================================================================================================================================================================


tree_t* New_tree_branch(info_tree* get_inform , tree_t* left , tree_t* right)
{
	assert(get_inform);

	tree_t* tree =(tree_t*)calloc(1 , sizeof(*tree));

	tree->data  = *get_inform;

	tree->right = right;
	tree->left  = left;

	CHECK(tree);

	return tree;

}

void tree_destruct(tree_t* tree)
{
	assert(tree);

	CHECK(tree);

    if(tree->left)  {  tree_destruct(tree->left); }
    if(tree->right) {  tree_destruct(tree->right);}

    tree->data.symbol  = ' ';
    tree->data.value   = POISON;

    tree->right = NULL;
    tree->left  = NULL;

	free(tree);   tree = NULL;

}

void  Print_tree(tree_t* tree)
{
	assert(tree);

	printf(" ( ");

	//if(tree->data.flag == OPERATION_TYPE)   { printf("%c " , tree->data.symbol);  }
	//if(tree->data.flag == CHISLO_TYPE)      { printf("%d " , tree->data.value);   }
	//if(tree->data.flag == VAR_TYPE)         { printf("%s"  , tree->data.var);     }
	//if(tree->data.flag == FUNCTION_TYPE)    { printf("%s"  , tree->data.func);    }



	if(tree->left)  { Print_tree(tree->left); }
	if(tree->right) { Print_tree(tree->right);}

	printf(" ) ");

}

void tree_dump(tree_t* tree)
{

    assert(tree);

    int cycle_analysis = tree_cycle_ok(tree);

    if(cycle_analysis == CYCLE_IN_TREE) {printf("Attention , there is cycle in this tree !");}

    Print_tree(tree);

}

//================================================================================================================================================================================


int tree_cycle_ok(tree_t* tree)
{
	assert(tree);

	int right_number = 0;
	int left_number  = 0;

    if(tree->left != NULL)  { left_number  = tree_cycle_ok(tree->left);  }
    if(tree->right != NULL) { right_number = tree_cycle_ok(tree->right); }

    if(left_number + right_number + 1 > MAX_TREE_SIZE) {return CYCLE_IN_TREE;}

	return left_number + right_number + 1;

}


//================================================================================================================================================================================


void Print_tree_postfiks(tree_t* tree)
{
	assert(tree);

	if(tree->left)  { Print_tree(tree->left); }
	if(tree->right) { Print_tree(tree->right);}


	//if(tree->data.flag == OPERATION_TYPE)    printf("%c" , tree->data.symbol);
	//if(tree->data.flag == CHISLO_TYPE)       printf("%d" , tree->data.value);
	//if(tree->data.flag == VAR_TYPE)          printf("%s" , tree->data.var);

}

void Print_tree_infiks(tree_t* tree)
{
	assert(tree);

	int first_f = importance(tree);
	if(tree->left)
    {

        int second_f = importance(tree->left);
        if(second_f > first_f)   printf("(");

    }


	if(tree->left)  { Print_tree_infiks(tree->left); }

	int first_i  = importance(tree);
	if(tree->right)
    {

        int second_i = importance(tree->right);
        if(second_i > first_i)  printf(")");

    }


    //if(tree->data.flag == OPERATION_TYPE)  printf("%c" , tree->data.symbol);
    //if(tree->data.flag == CHISLO_TYPE)     printf("%d" , tree->data.value);
    //if(tree->data.flag == VAR_TYPE)        printf("%s"  , tree->data.var);
	//if(tree->data.flag == FUNCTION_TYPE)   printf("%s"  , tree->data.func);

	if(tree->right) { Print_tree_infiks(tree->right);}

}

//================================================================================================================================================================================

tree_t* copy_tree(tree_t* tree )
{

    assert(tree);

    tree_t* right_copy = NULL;
    tree_t* left_copy  = NULL;

    if(tree->left != NULL)  {  left_copy  = copy_tree(tree->left) ; }
    else
    {
        left_copy  = NULL;
    }

    if(tree->right != NULL) {  right_copy = copy_tree(tree->right); }
    else
    {
        right_copy = NULL;
    }


    tree_t* cpy_tree = New_tree_branch(&(tree->data) , left_copy , right_copy);

    return cpy_tree;


}

//================================================================================================================================================================================

int importance(tree_t* tree)
{

    assert(tree);

/*
    if(tree->data.flag == CHISLO_TYPE)   return 5;
    if(tree->data.flag == VAR_TYPE   )   return 5;

    if(tree->data.flag == FUNCTION_TYPE) return 5;

    if(tree->data.flag == OPERATION_TYPE)
    {

        if(tree->data.symbol == '+') return 2;
        if(tree->data.symbol == '-') return 2;

        if(tree->data.symbol == '*') return 3;
        if(tree->data.symbol == '/') return 3;

        if(tree->data.symbol == '^') return 4;
    }

*/
    return 1;

}

//================================================================================================================================================================================


















